package io.gitee.zhangbinhub.admin.base

import com.mybatisflex.core.paginate.Page
import com.mybatisflex.core.query.QueryChain
import com.mybatisflex.core.table.TableInfoFactory
import io.gitee.zhangbinhub.acp.core.common.CommonTools
import io.gitee.zhangbinhub.admin.po.QueryParam
import io.gitee.zhangbinhub.admin.vo.CustomerQueryPageVo
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Sort

/**
 * @since JDK 11
 */
abstract class BaseService {
    protected inline fun <reified T> doPageQuery(
        queryParam: QueryParam,
        queryChain: QueryChain<T>,
        withRelations: Boolean = false
    ): CustomerQueryPageVo<T> {
        if (!CommonTools.isNullStr(queryParam.orderName)) {
            val tableInfo = TableInfoFactory.ofEntityClass(T::class.java)
            queryParam.orderName!!.split(",").forEach { orderProperty ->
                queryChain.orderBy(
                    tableInfo.getQueryColumnByProperty(orderProperty),
                    queryParam.orderCommand.equals("asc", true)
                )
            }
        }
        return (if (withRelations) {
            queryChain.withRelations().page(Page(queryParam.currPage, queryParam.pageSize))
        } else {
            queryChain.page(Page(queryParam.currPage, queryParam.pageSize))
        }).let { pageResult ->
            CustomerQueryPageVo(
                content = pageResult.records,
                totalElements = pageResult.totalRow,
                currPage = queryParam.currPage!!,
                pageSize = queryParam.pageSize!!
            )
        }
    }

    protected fun buildPageRequest(queryParam: QueryParam): PageRequest =
        if (CommonTools.isNullStr(queryParam.orderName) || CommonTools.isNullStr(queryParam.orderCommand)) {
            PageRequest.of(queryParam.currPage!! - 1, queryParam.pageSize!!)
        } else {
            var direction: Sort.Direction = Sort.Direction.ASC
            if (queryParam.orderCommand!!.startsWith("desc", ignoreCase = true)) {
                direction = Sort.Direction.DESC
            }
            PageRequest.of(
                queryParam.currPage!! - 1,
                queryParam.pageSize!!,
                direction,
                *queryParam.orderName!!.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
            )
        }

    protected fun <T : BaseTreeEntity<T>> formatToTreeList(map: Map<String, T>): MutableList<T> {
        val result: MutableList<T> = mutableListOf()
        map.forEach { (_, value) ->
            if (map.containsKey(value.parentId)) {
                map.getValue(value.parentId).children.add(value)
            } else {
                result.add(value)
            }
        }
        return result
    }

}
